/**
 * Copyright 2020 jianggujin (www.jianggujin.com).
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *  
 *      http://www.apache.org/licenses/LICENSE-2.0
 *  
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.jianggujin.dbfly.mybatis.entity;

import com.jianggujin.dbfly.mybatis.util.JLambdaPropertyUtils;
import com.jianggujin.dbfly.mybatis.util.JPropertyFunction;

/**
 * @author jianggujin
 *
 */
public class JLambdaCriteria<T> {
    private final JCriteria criteria;

    protected JLambdaCriteria(JCriteria criteria) {
        this.criteria = criteria;
    }

    /*************************** AND相关操作 *************************/
    public <R> JLambdaCriteria<T> andIsNull(JPropertyFunction<T, R> function) {
        this.criteria.andIsNull(JLambdaPropertyUtils.resolve(function));
        return this;
    }

    public <R> JLambdaCriteria<T> andIsNotNull(JPropertyFunction<T, R> function) {
        this.criteria.andIsNotNull(JLambdaPropertyUtils.resolve(function));
        return this;
    }

    public <R> JLambdaCriteria<T> andEqualTo(JPropertyFunction<T, R> function, R value) {
        this.criteria.andEqualTo(JLambdaPropertyUtils.resolve(function), value);
        return this;
    }

    public <R> JLambdaCriteria<T> andEq(JPropertyFunction<T, R> function, R value) {
        this.criteria.andEq(JLambdaPropertyUtils.resolve(function), value);
        return this;
    }

    public <R> JLambdaCriteria<T> andNotEqualTo(JPropertyFunction<T, R> function, R value) {
        this.criteria.andNotEqualTo(JLambdaPropertyUtils.resolve(function), value);
        return this;
    }

    public <R> JLambdaCriteria<T> andNe(JPropertyFunction<T, R> function, R value) {
        this.criteria.andNe(JLambdaPropertyUtils.resolve(function), value);
        return this;
    }

    public <R> JLambdaCriteria<T> andGreaterThan(JPropertyFunction<T, R> function, R value) {
        this.criteria.andGreaterThan(JLambdaPropertyUtils.resolve(function), value);
        return this;
    }

    public <R> JLambdaCriteria<T> andGt(JPropertyFunction<T, R> function, R value) {
        this.criteria.andGt(JLambdaPropertyUtils.resolve(function), value);
        return this;
    }

    public <R> JLambdaCriteria<T> andGreaterThanOrEqualTo(JPropertyFunction<T, R> function, R value) {
        this.criteria.andGreaterThanOrEqualTo(JLambdaPropertyUtils.resolve(function), value);
        return this;
    }

    public <R> JLambdaCriteria<T> andGe(JPropertyFunction<T, R> function, R value) {
        this.criteria.andGe(JLambdaPropertyUtils.resolve(function), value);
        return this;
    }

    public <R> JLambdaCriteria<T> andLessThan(JPropertyFunction<T, R> function, R value) {
        this.criteria.andLessThan(JLambdaPropertyUtils.resolve(function), value);
        return this;
    }

    public <R> JLambdaCriteria<T> andLt(JPropertyFunction<T, R> function, R value) {
        this.criteria.andLt(JLambdaPropertyUtils.resolve(function), value);
        return this;
    }

    public <R> JLambdaCriteria<T> andLessThanOrEqualTo(JPropertyFunction<T, R> function, R value) {
        this.criteria.andLessThanOrEqualTo(JLambdaPropertyUtils.resolve(function), value);
        return this;
    }

    public <R> JLambdaCriteria<T> andLe(JPropertyFunction<T, R> function, R value) {
        this.criteria.andLe(JLambdaPropertyUtils.resolve(function), value);
        return this;
    }

    public <R> JLambdaCriteria<T> andIn(JPropertyFunction<T, R> function, Iterable<R> values) {
        this.criteria.andIn(JLambdaPropertyUtils.resolve(function), values);
        return this;
    }

    public <R> JLambdaCriteria<T> andNotIn(JPropertyFunction<T, R> function, Iterable<R> values) {
        this.criteria.andNotIn(JLambdaPropertyUtils.resolve(function), values);
        return this;
    }

    public <R> JLambdaCriteria<T> andBetween(JPropertyFunction<T, R> function, R value1, R value2) {
        this.criteria.andBetween(JLambdaPropertyUtils.resolve(function), value1, value2);
        return this;
    }

    public <R> JLambdaCriteria<T> andNotBetween(JPropertyFunction<T, R> function, R value1, R value2) {
        this.criteria.andNotBetween(JLambdaPropertyUtils.resolve(function), value1, value2);
        return this;
    }

    public JLambdaCriteria<T> andLike(JPropertyFunction<T, String> function, String value) {
        this.criteria.andLike(JLambdaPropertyUtils.resolve(function), value);
        return this;
    }

    public JLambdaCriteria<T> andLikeLeft(JPropertyFunction<T, String> function, String value) {
        this.criteria.andLikeLeft(JLambdaPropertyUtils.resolve(function), value);
        return this;
    }

    public JLambdaCriteria<T> andLikeRight(JPropertyFunction<T, String> function, String value) {
        this.criteria.andLikeRight(JLambdaPropertyUtils.resolve(function), value);
        return this;
    }

    public JLambdaCriteria<T> andNotLike(JPropertyFunction<T, String> function, String value) {
        this.criteria.andNotLike(JLambdaPropertyUtils.resolve(function), value);
        return this;
    }

    public JLambdaCriteria<T> andNotLikeLeft(JPropertyFunction<T, String> function, String value) {
        this.criteria.andNotLikeLeft(JLambdaPropertyUtils.resolve(function), value);
        return this;
    }

    public JLambdaCriteria<T> andNotLikeRight(JPropertyFunction<T, String> function, String value) {
        this.criteria.andNotLikeRight(JLambdaPropertyUtils.resolve(function), value);
        return this;
    }

    /*************************** OR相关操作 *************************/
    public <R> JLambdaCriteria<T> orIsNull(JPropertyFunction<T, R> function) {
        this.criteria.orIsNull(JLambdaPropertyUtils.resolve(function));
        return this;
    }

    public <R> JLambdaCriteria<T> orIsNotNull(JPropertyFunction<T, R> function) {
        this.criteria.orIsNotNull(JLambdaPropertyUtils.resolve(function));
        return this;
    }

    public <R> JLambdaCriteria<T> orEqualTo(JPropertyFunction<T, R> function, R value) {
        this.criteria.orEqualTo(JLambdaPropertyUtils.resolve(function), value);
        return this;
    }

    public <R> JLambdaCriteria<T> orEq(JPropertyFunction<T, R> function, R value) {
        this.criteria.orEq(JLambdaPropertyUtils.resolve(function), value);
        return this;
    }

    public <R> JLambdaCriteria<T> orNotEqualTo(JPropertyFunction<T, R> function, R value) {
        this.criteria.orNotEqualTo(JLambdaPropertyUtils.resolve(function), value);
        return this;
    }

    public <R> JLambdaCriteria<T> orNe(JPropertyFunction<T, R> function, R value) {
        this.criteria.orNe(JLambdaPropertyUtils.resolve(function), value);
        return this;
    }

    public <R> JLambdaCriteria<T> orGreaterThan(JPropertyFunction<T, R> function, R value) {
        this.criteria.orGreaterThan(JLambdaPropertyUtils.resolve(function), value);
        return this;
    }

    public <R> JLambdaCriteria<T> orGt(JPropertyFunction<T, R> function, R value) {
        this.criteria.orGt(JLambdaPropertyUtils.resolve(function), value);
        return this;
    }

    public <R> JLambdaCriteria<T> orGreaterThanOrEqualTo(JPropertyFunction<T, R> function, R value) {
        this.criteria.orGreaterThanOrEqualTo(JLambdaPropertyUtils.resolve(function), value);
        return this;
    }

    public <R> JLambdaCriteria<T> orGe(JPropertyFunction<T, R> function, R value) {
        this.criteria.orGe(JLambdaPropertyUtils.resolve(function), value);
        return this;
    }

    public <R> JLambdaCriteria<T> orLessThan(JPropertyFunction<T, R> function, R value) {
        this.criteria.orLessThan(JLambdaPropertyUtils.resolve(function), value);
        return this;
    }

    public <R> JLambdaCriteria<T> orLt(JPropertyFunction<T, R> function, R value) {
        this.criteria.orLt(JLambdaPropertyUtils.resolve(function), value);
        return this;
    }

    public <R> JLambdaCriteria<T> orLessThanOrEqualTo(JPropertyFunction<T, R> function, R value) {
        this.criteria.orLessThanOrEqualTo(JLambdaPropertyUtils.resolve(function), value);
        return this;
    }

    public <R> JLambdaCriteria<T> orLe(JPropertyFunction<T, R> function, R value) {
        this.criteria.orLe(JLambdaPropertyUtils.resolve(function), value);
        return this;
    }

    public <R> JLambdaCriteria<T> orIn(JPropertyFunction<T, R> function, Iterable<R> values) {
        this.criteria.orIn(JLambdaPropertyUtils.resolve(function), values);
        return this;
    }

    public <R> JLambdaCriteria<T> orNotIn(JPropertyFunction<T, R> function, Iterable<R> values) {
        this.criteria.orNotIn(JLambdaPropertyUtils.resolve(function), values);
        return this;
    }

    public <R> JLambdaCriteria<T> orBetween(JPropertyFunction<T, R> function, R value1, R value2) {
        this.criteria.orBetween(JLambdaPropertyUtils.resolve(function), value1, value2);
        return this;
    }

    public <R> JLambdaCriteria<T> orNotBetween(JPropertyFunction<T, R> function, R value1, R value2) {
        this.criteria.orNotBetween(JLambdaPropertyUtils.resolve(function), value1, value2);
        return this;
    }

    public JLambdaCriteria<T> orLike(JPropertyFunction<T, String> function, String value) {
        this.criteria.orLike(JLambdaPropertyUtils.resolve(function), value);
        return this;
    }

    public JLambdaCriteria<T> orLikeLeft(JPropertyFunction<T, String> function, String value) {
        this.criteria.orLikeLeft(JLambdaPropertyUtils.resolve(function), value);
        return this;
    }

    public JLambdaCriteria<T> orLikeRight(JPropertyFunction<T, String> function, String value) {
        this.criteria.orLikeRight(JLambdaPropertyUtils.resolve(function), value);
        return this;
    }

    public JLambdaCriteria<T> orNotLike(JPropertyFunction<T, String> function, String value) {
        this.criteria.orNotLike(JLambdaPropertyUtils.resolve(function), value);
        return this;
    }

    public JLambdaCriteria<T> orNotLikeLeft(JPropertyFunction<T, String> function, String value) {
        this.criteria.orNotLikeLeft(JLambdaPropertyUtils.resolve(function), value);
        return this;
    }

    public JLambdaCriteria<T> orNotLikeRight(JPropertyFunction<T, String> function, String value) {
        this.criteria.orNotLikeRight(JLambdaPropertyUtils.resolve(function), value);
        return this;
    }

    /*************************** 链式相关操作 *************************/
    public <R> JLambdaCriteria<T> isNull(JPropertyFunction<T, R> function) {
        this.criteria.isNull(JLambdaPropertyUtils.resolve(function));
        return this;
    }

    public <R> JLambdaCriteria<T> isNotNull(JPropertyFunction<T, R> function) {
        this.criteria.isNotNull(JLambdaPropertyUtils.resolve(function));
        return this;
    }

    public <R> JLambdaCriteria<T> equalTo(JPropertyFunction<T, R> function, R value) {
        this.criteria.equalTo(JLambdaPropertyUtils.resolve(function), value);
        return this;
    }

    public <R> JLambdaCriteria<T> eq(JPropertyFunction<T, R> function, R value) {
        this.criteria.eq(JLambdaPropertyUtils.resolve(function), value);
        return this;
    }

    public <R> JLambdaCriteria<T> notEqualTo(JPropertyFunction<T, R> function, R value) {
        this.criteria.notEqualTo(JLambdaPropertyUtils.resolve(function), value);
        return this;
    }

    public <R> JLambdaCriteria<T> ne(JPropertyFunction<T, R> function, R value) {
        this.criteria.ne(JLambdaPropertyUtils.resolve(function), value);
        return this;
    }

    public <R> JLambdaCriteria<T> greaterThan(JPropertyFunction<T, R> function, R value) {
        this.criteria.greaterThan(JLambdaPropertyUtils.resolve(function), value);
        return this;
    }

    public <R> JLambdaCriteria<T> gt(JPropertyFunction<T, R> function, R value) {
        this.criteria.gt(JLambdaPropertyUtils.resolve(function), value);
        return this;
    }

    public <R> JLambdaCriteria<T> greaterThanOrEqualTo(JPropertyFunction<T, R> function, R value) {
        this.criteria.greaterThanOrEqualTo(JLambdaPropertyUtils.resolve(function), value);
        return this;
    }

    public <R> JLambdaCriteria<T> ge(JPropertyFunction<T, R> function, R value) {
        this.criteria.ge(JLambdaPropertyUtils.resolve(function), value);
        return this;
    }

    public <R> JLambdaCriteria<T> lessThan(JPropertyFunction<T, R> function, R value) {
        this.criteria.lessThan(JLambdaPropertyUtils.resolve(function), value);
        return this;
    }

    public <R> JLambdaCriteria<T> lt(JPropertyFunction<T, R> function, R value) {
        this.criteria.lt(JLambdaPropertyUtils.resolve(function), value);
        return this;
    }

    public <R> JLambdaCriteria<T> lessThanOrEqualTo(JPropertyFunction<T, R> function, R value) {
        this.criteria.lessThanOrEqualTo(JLambdaPropertyUtils.resolve(function), value);
        return this;
    }

    public <R> JLambdaCriteria<T> le(JPropertyFunction<T, R> function, R value) {
        this.criteria.le(JLambdaPropertyUtils.resolve(function), value);
        return this;
    }

    public <R> JLambdaCriteria<T> in(JPropertyFunction<T, R> function, Iterable<R> values) {
        this.criteria.in(JLambdaPropertyUtils.resolve(function), values);
        return this;
    }

    public <R> JLambdaCriteria<T> notIn(JPropertyFunction<T, R> function, Iterable<R> values) {
        this.criteria.notIn(JLambdaPropertyUtils.resolve(function), values);
        return this;
    }

    public <R> JLambdaCriteria<T> between(JPropertyFunction<T, R> function, R value1, R value2) {
        this.criteria.between(JLambdaPropertyUtils.resolve(function), value1, value2);
        return this;
    }

    public <R> JLambdaCriteria<T> notBetween(JPropertyFunction<T, R> function, R value1, R value2) {
        this.criteria.notBetween(JLambdaPropertyUtils.resolve(function), value1, value2);
        return this;
    }

    public JLambdaCriteria<T> like(JPropertyFunction<T, String> function, String value) {
        this.criteria.like(JLambdaPropertyUtils.resolve(function), value);
        return this;
    }

    public JLambdaCriteria<T> likeLeft(JPropertyFunction<T, String> function, String value) {
        this.criteria.likeLeft(JLambdaPropertyUtils.resolve(function), value);
        return this;
    }

    public JLambdaCriteria<T> likeRight(JPropertyFunction<T, String> function, String value) {
        this.criteria.likeRight(JLambdaPropertyUtils.resolve(function), value);
        return this;
    }

    public JLambdaCriteria<T> notLike(JPropertyFunction<T, String> function, String value) {
        this.criteria.notLike(JLambdaPropertyUtils.resolve(function), value);
        return this;
    }

    public JLambdaCriteria<T> notLikeLeft(JPropertyFunction<T, String> function, String value) {
        this.criteria.notLikeLeft(JLambdaPropertyUtils.resolve(function), value);
        return this;
    }

    public JLambdaCriteria<T> notLikeRight(JPropertyFunction<T, String> function, String value) {
        this.criteria.notLikeRight(JLambdaPropertyUtils.resolve(function), value);
        return this;
    }

    /**
     * 开始AND
     * 
     * @return
     */
    public JLambdaCriteria<T> and() {
        this.criteria.and();
        return this;
    }

    /**
     * 开始OR
     * 
     * @return
     */
    public JLambdaCriteria<T> or() {
        this.criteria.or();
        return this;
    }

    public JCriteria getCriteria() {
        return criteria;
    }
}